<?php
/**
 * @package qBase
 * @subpackage sql
 *
 */

/**
 * QSqlConnection represents a SqlConnection
 * @package qBase
 * @subpackage sql
 */
abstract class QSqlConnection extends QObject 
{
	/**
	 * The MySql Connection type
	 *
	 */
	const TypeMySql = 1;
	/**
	 * The host
	 *
	 * @var string
	 */
	protected $host;
	/**
	 * The port
	 *
	 * @var integer
	 */
	protected $port;
	/**
	 * The user
	 *
	 * @var string
	 */
	protected $user;
	/**
	 * The password
	 *
	 * @var string
	 */
	protected $pass;
	/**
	 * The default database to use
	 *
	 * @var string
	 */
	protected $db;
	/**
	 * The char that escapes table names, field names and so on
	 *
	 * @var string
	 */
	protected $escape_char;

	/**
	 * The reference to the native SQL connection
	 *
	 * @var resource
	 */
	protected $reference;
	
	/**
	 * Constructs a QSqlConnection object
	 *
	 * @param string $host
	 * @param integer $port
	 * @param string $user
	 * @param string $pass
	 * @param string $db
	 */
	public function __construct($host, $port, $user, $pass, $db = null)
	{
		parent::__construct();
		
		$this->host = $host;
		$this->port = $port;
		$this->user = $user;
		$this->pass = $pass;
		$this->db = $db;
	}
	
	/**
	 * Gets the default database if any was set
	 *
	 * @return string
	 */
	public function getDefaultDatabase()
	{
		return $this->db;
	}

	/**
	 * Connect to the database
	 *
	 */
	public abstract function connect();
	/**
	 * Closes the connection to the database
	 *
	 */
	public abstract function close();
	/**
	 * Executes a query
	 *
	 * @param mixed $query Can be a string or a QSqlQuery
	 * @return resource returns a link to the result set
	 */
	public abstract function query($query);
	/**
	 * Executes a query on the specified database
	 *
	 * @param string $query
	 * @param string $db
	 * @return returns a link to the result set
	 */
	public abstract function queryDb($query, $db);
	/**
	 * Executes an insert query and reurns the id
	 *
	 * @param string $query
	 * @return mixed the id of the inserted record
	 */
	public abstract function insert($query);
	/**
	 * Gets the ID of the last inserted value. Only works on auto increments.
	 *
	 * @return integer
	 */
	public abstract function getInsertId();
	/**
	 * Fetches the row from a query result
	 *
	 * @param resource $result
	 * @return array Associative array (column => value)
	 */
	public abstract function fetchRow($result);
	/**
	 * Fetches the value from the next row using the specified key
	 *
	 * @param mixed $result
	 * @param mixed $key
	 * @return mixed
	 */
	public abstract function fetchValue($result, $key);
	/**
	 * Fetches the row from a query result as an array with numeric keys
	 *
	 * @param resource $result 
	 * @return array Associative array (index => value)
	 */
	public abstract function fetchArray($result);
	/**
	 * Fetches the row from a query result as an object
	 *
	 * @param resource $result
	 * @return object
	 */
	public abstract function fetchObject($result);
	/**
	 * Counts the number of records resuled on a SELECT query
	 *
	 * @param mixed $result
	 * @return integer
	 */
	public abstract function countRows($result);
	/**
	 * Sets the current record in a recordset
	 *
	 * @param mixed $result
	 * @param integer $position
	 */
	public abstract function setCurrentRow($result, $position);
	/**
	 * Gets the default charset for this connection
	 * @return string 
	 */
	public abstract function getClientEncoding();
	
	/**
	 * Sets the connection encoding
	 *
	 * @param string $encoding
	 */
	public abstract function setClientEncoding($encoding);
	/**
	 * Escapes a string for this connection
	 *
	 * @param string $str
	 * @return string
	 */
	public abstract function escapeString($str);
	/**
	 * Escapes the name of a database, table, column, alias and so on
	 *
	 * @param string $str
	 */
	public abstract function escapeName($str);
	/**
	 * Sets a database as the default for this connection
	 *
	 * @param string $db
	 */
	public abstract function selectDb($db);

	/**
	 * Gets the list of all databases available for this connection. Returns an array of QSqlDatabase(s).
	 * If refresh is set to true the list will be read again
	 * 
	 * @param boolean $refresh
	 * @return array
	 */
	public abstract function getDatabases($refresh = false);
	
	/**
	 * Creates the specified database
	 *
	 * @param QSqlDatabase $db
	 */
	public abstract function createDatabase(QSqlDatabase $db);
	
	/**
	 * Tests if the specified database name exists for the current connection.
	 *
	 * @param string $db_name
	 * @return boolean
	 */
	public abstract function hasDatabase($db_name);
	/**
	 * Gets the escape char. If it's brackets returns two characters
	 *
	 * @return string
	 */
	public function getEscapeChar()
	{
		return $this->escape_char;
	}
	/**
	 * Sets the escape char. If it's brackets then two characters must be specified
	 *
	 * @param string $char
	 */
	public function setEscapeChar($char)
	{
		$this->escape_char = $char;
	}
	/**
	 * Gets the database object for the specified database name
	 *
	 * @param string $db_name
	 * @return QSqlDatabase
	 */
	public abstract function getDatabaseInfo($db_name);
	/**
	 * Creates a table based on the QSqlTable structure
	 *
	 * @param string $database
	 * @param QSqlTable $table
	 * @param boolean $drop_if_exists
	 */
	public abstract function createTable($database, QSqlTable $table, $drop_if_exists = false);
	
	/**
	 * Gets only the first row from a query. LIMIT must be specified in query if it's desired
	 * Returns null if the first row does not exist
	 *
	 * @param string $query
	 * @return mixed
	 */
	public function queryOneRow($query)
	{
		return $this->fetchRow( $this->query($query) );
	}
	
	/**
	 * Gets a single value from the first row of the query result. LIMIT must be specified in query if it's desired
	 * Returns null if the first row does not exist or the field name in the row does not exists
	 *
	 * @param string $query
	 * @param mixed $field_name If it's a number then fetchArray will be used instead of fetchRow
	 * @return mixed
	 */
	public function queryOneValue($query, $field_name)
	{
		if (is_numeric($field_name))
			$row = $this->fetchArray( $this->query($query) );
		else 
			$row = $this->fetchRow( $this->query($query) );

		if ($row && isset($row[$field_name]))
			return $row[$field_name];
		else
			return null;
	}
	
	/**
	 * Gets the accepted charsets by the SQL engine
	 *
	 * @param boolean $refresh If true it forces a refresh, if not the value will be taken from the cache
	 * @return array Array of strings
	 */
	public abstract function getAcceptedCharsets($refresh = false);
	
	/**
	 * Sets the table collation
	 *
	 * @param string $database_name
	 * @param string $table_name
	 * @param string $collation
	 */
	public abstract function setTableCollation($database_name, $table_name, $collation);
	
	/**
	 * Sets the table charset
	 *
	 * @param string $database_name
	 * @param string $table_name
	 * @param string $charset
	 */
	public abstract function setTableCharset($database_name, $table_name, $charset);
	
	/**
	 * Sets the table's engine
	 *
	 * @param string $database_name
	 * @param string $table_name
	 * @param string $engine
	 */
	public abstract function setTableEngine($database_name, $table_name, $engine);
	
	/**
	 * Sets the table comment
	 *
	 * @param string $database_name
	 * @param string $table_name
	 * @param string $comment
	 */
	public abstract function setTableComment($database_name, $table_name, $comment);
	
	/**
	 * Renames a table
	 *
	 * @param string $database_name
	 * @param string $table_name
	 * @param string $new_name
	 */
	public abstract function renameTable($database_name, $table_name, $new_name);
	
	/**
	 * Removes an index from the table
	 *
	 * @param string $database_name
	 * @param string $table_name
	 * @param string $index_name
	 */
	public abstract function removeTableIndex($database_name, $table_name, $index_name);
	
	/**
	 * Updates an index
	 *
	 * @param string $database_name
	 * @param string $table_name
	 * @param QSqlTableIndex $index
	 */
	public abstract function updateTableIndex($database_name, $table_name, QSqlTableIndex $index);
	
	/**
	 * Ads an index to the table
	 *
	 * @param string $database_name
	 * @param string $table_name
	 * @param QSqlTableIndex $index
	 */
	public abstract function addTableIndex($database_name, $table_name, QSqlTableIndex $index);
	
	/**
	 * Removes the specified table fields. The fields are specified as an array of strings
	 *
	 * @param string $database_name
	 * @param string $table_name
	 * @param string $fields_names Array of string
	 */
	public abstract function removeTableFields($database_name, $table_name, $fields_names);
	
	/**
	 * Updates the specified table fields. If the fields do not exist an exception will be throwm
	 *
	 * @param string $database_name
	 * @param string $table_name
	 * @param array $fields Array of QSqlTableField
	 */
	public abstract function updateTableFields($database_name, $table_name, $fields);
	
	/**
	 * Ads the specified fields to the table
	 *
	 * @param string $database_name
	 * @param string $table_name
	 * @param array $fields Array of QSqlTableField
	 */
	public abstract function addTableFields($database_name, $table_name, $fields);
	
	/**
	 * Drops the table from the database
	 *
	 * @param string $database_name
	 * @param string $table_name
	 */
	public abstract function dropTable($database_name, $table_name);
	
	/**
	 * Gets the full table information including indexes and fields, collation, charset, engine, etc ...
	 *
	 * @param string $database_name
	 * @param string $table_name
	 * @return QSqlTable
	 */
	public abstract function getTableInfo($database_name, $table_name);
	
	/**
	 * Sets the database charset
	 *
	 * @param string $db_name
	 * @param string $charset
	 */
	public abstract function setDatabaseCharset($db_name, $charset);
	
	/**
	 * Sets the database's collation. It's safe to change the charset before using a collation of a different set.
	 *
	 * @param string $db_name
	 * @param string $collation
	 */
	public abstract function setDatabaseCollation($db_name, $collation);
	
	/**
	 * Renames the database
	 *
	 * @param string $db_name
	 * @param string $new_name
	 */
	public abstract function renameDatabase($db_name, $new_name);

	/**
	 * Determines if the specified database contains the table
	 *
	 * @param string $database_name
	 * @param string $table_name
	 * @return boolean
	 */
	public abstract function hasTable($database_name, $table_name);
	
	/**
	 * Empties the table and resests all indexes and autoincrements. This should 
	 * be the equivalent of a table drop and recreation.
	 *
	 * @param string $database_name
	 * @param string $table_name
	 */
	public abstract function truncateTable($database_name, $table_name);
	
	/**
	 * Transforms a QSqlQuery object into an SQL query string
	 *
	 * @param QSqlQuery $query
	 * @return string
	 */
	public abstract function parseSqlQuery(QSqlQuery $query);
	/**
	 * Gets an array of strings containing the names of the tables in the database
	 *
	 * @param string $database_name
	 * @return array Array of strings
	 */
	public abstract function getTablesInDatabase($database_name);
}